﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace PongGame
{

    public class Sprite
    {
        protected Texture2D textureImage;
        protected Rectangle rect;
        protected Rectangle? sourceRect;
        protected Color color;
        protected Vector2 speed;
        protected Vector2 position;

        public Vector2 Direction
        {
            get { return speed; }
        }

        public Sprite(Texture2D TextureImage,Vector2 position, Vector2 speed,
           Rectangle Rect, Rectangle? SourceRect, Color Color)
        {
            textureImage = TextureImage;
            rect = Rect;
            sourceRect = SourceRect;
            color = Color;
            this.position = position;
            this.speed = speed;
        }

        public virtual void Update(GameTime gameTime, Rectangle clientBounds)
        {
            

        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(textureImage,
               new Rectangle(
                     rect.X * Game1.ScreenWidth / 1024,
                     rect.Y * Game1.ScreenHeight / 768,
                     rect.Width * Game1.ScreenWidth / 1024,
                     rect.Height * Game1.ScreenHeight / 768),
                     sourceRect, color);
        }
 
    } 

    //Game component that implements IUpdateable
    public class SpriteManager : Microsoft.Xna.Framework.DrawableGameComponent
    {
        SpriteBatch spriteBatch;
        Ball ball;
        MenuManager MenuMgr;
        Paddle RedPaddle;
        Paddle BluePaddle;
        BackGround backGround;
        Texture2D menuTexture, gameTexture;
        AudioEngine audioEngine;
        WaveBank waveBank;
        SoundBank soundBank;

        List<Sprite> SpriteList = new List<Sprite>();

        static public readonly Rectangle
            //The numbers locate the rect around draw on the sprite sheet
            XnaPongLogoRect = new Rectangle(0, 0, 512, 110),
            MenuSingleplayerRect = new Rectangle(0, 110, 512, 38),
            MenuMultiplayerRect = new Rectangle(0, 148, 512, 38),
            MenuExitRect = new Rectangle(0, 185, 512, 38),

            GameLivesRect = new Rectangle(0, 222, 100, 34),
            GameRedWonRect = new Rectangle(151, 222, 155, 34),
            GameBlueWonRect = new Rectangle(338, 222, 165, 34),
            GameRedPaddleRect = new Rectangle(23, 0, 22, 92),
            GameBluePaddleRect = new Rectangle(0, 0, 22, 92),
            GameBallRect = new Rectangle(1, 94, 33, 33),
            GameSmallBallRect = new Rectangle(37, 108, 19, 19);

        //Constructor
        public SpriteManager(Game game): base(game)
        {
            // TODO: Construct any child components here
        }

        public override void Initialize()
        {
            
            base.Initialize();
        }

        protected override void LoadContent()
        {
           spriteBatch = new SpriteBatch(Game.GraphicsDevice);

           audioEngine = new AudioEngine("Content/PongSound.xgs");
           waveBank = new WaveBank(audioEngine, "Content/Wave Bank.xwb");
           if (waveBank != null)
               soundBank = new SoundBank(audioEngine, "Content/Sound Bank.xsb");

           // Load all our content
           backGround = new BackGround(
              Game.Content.Load<Texture2D>("SpaceBackground"),
              Vector2.Zero, Vector2.Zero,
              new Rectangle(0, 0, Game1.ScreenWidth, Game1.ScreenHeight),
              null, Color.LightGray);

           menuTexture = Game.Content.Load<Texture2D>("PongMenu");
           gameTexture = Game.Content.Load<Texture2D>("PongGame");

            //Create menu manager
           MenuMgr = new MenuManager(this, Game, soundBank);

           base.LoadContent();
        }


        public override void Update(GameTime gameTime)
        {

            MenuMgr.Update();

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            backGround.Draw(spriteBatch);

            // No need to render if we got no sprites this frame
            if (SpriteList.Count == 0)
                return;

            // Start rendering sprites
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);

            // Render all sprites
            foreach (Sprite sprite in SpriteList)
                sprite.Draw(spriteBatch);

            // We are done, draw everything on screen with help of the end method.
            spriteBatch.End();

            // Kill list of remembered sprites
            SpriteList.Clear();
        }

        public void RenderSprite(Texture2D texture, Rectangle rect, Rectangle? sourceRect, Color color)
        {
            SpriteList.Add(new Sprite(texture, Vector2.Zero, Vector2.Zero, rect, sourceRect, color));
        }

        public void RenderSprite(Texture2D texture, Rectangle rect, Rectangle? sourceRect)
        {
            RenderSprite(texture, rect, sourceRect, Color.White);
        }

        public void RenderSprite(Texture2D texture, Rectangle rect, Color color)
        {
            RenderSprite(texture, rect, null, color);
        }

        public void RenderSprite(Texture2D texture, Rectangle rect)
        {
            RenderSprite(texture, rect, null, Color.White);
        }

        public void RenderSprite(Texture2D texture)
        {
            RenderSprite(texture, new Rectangle(0, 0, 1024, 768), null, Color.White);
        }

        public void RenderSprite(Texture2D texture, int x, int y, Rectangle? sourceRect, Color color)
        {
            RenderSprite(texture, new Rectangle(x, y, sourceRect.Value.Width, sourceRect.Value.Height),
                sourceRect, color);
        }

        public void RenderSprite(Texture2D texture, int x, int y, Rectangle? sourceRect)
        {
            RenderSprite(texture,
                new Rectangle(x, y, sourceRect.Value.Width, sourceRect.Value.Height),
                sourceRect, Color.White);
        }

        public void PrepareSpriteMenu(int menuItemNum)
        {
            //Set up location for the menu items on the game screen
            int XnaPongLogoRecX = 512 - XnaPongLogoRect.Width / 2;
            int XnaPongLogoRecY = 150;
            int SinglePlayerRectX = 512 - MenuSingleplayerRect.Width / 2;
            int SinglePlayerRectY = 300;
            int MultiPlayerRectX = 512 - MenuMultiplayerRect.Width / 2;
            int MultiPlayerRectY = 350;
            int MenuExitRectX = 512 - MenuExitRect.Width / 2;
            int MenuExitRectY = 400;

            RenderSprite(menuTexture, XnaPongLogoRecX, XnaPongLogoRecY, XnaPongLogoRect);
            RenderSprite(menuTexture, SinglePlayerRectX, SinglePlayerRectY, MenuSingleplayerRect, menuItemNum == 0 ? Color.Orange : Color.White);
            RenderSprite(menuTexture, MultiPlayerRectX, MultiPlayerRectY, MenuMultiplayerRect, menuItemNum == 1 ? Color.Orange : Color.White);
            RenderSprite(menuTexture, MenuExitRectX, MenuExitRectY, MenuExitRect, menuItemNum == 2 ? Color.Orange : Color.White);
        }

        public void ShowLives()
        {
            // Support for both Windows monitors and TV screens on the Xbox 360!
            int xPos = 2;
            int yPos = 2;
#if XBOX360
            xPos += Window.ClientBounds.Width / 24;
            yPos += Window.ClientBounds.Height / 24;
#endif
            // Left players lives
            RenderSprite(menuTexture, xPos, yPos, GameLivesRect);

            for (int num = 0; num < MenuMgr.GameManager.LeftPlayerLives; num++)
                RenderSprite(gameTexture,
                    xPos + GameLivesRect.Width + GameSmallBallRect.Width * num - 2,
                    yPos + 7,
                    GameSmallBallRect);

            // Right players lives
            int rightX = 1024 - GameLivesRect.Width - GameSmallBallRect.Width * 3 - xPos - 2;

            RenderSprite(menuTexture, rightX, yPos, GameLivesRect);
            for (int num = 0; num < MenuMgr.GameManager.RightPlayerLives; num++)
                RenderSprite(gameTexture,
                    rightX + GameLivesRect.Width + GameSmallBallRect.Width * num - 2,
                    yPos + 7,
                    GameSmallBallRect);
        }

        public void RenderBall()
        {
            RenderSprite(gameTexture,
                (int)((0.05f + 0.9f * MenuMgr.GameManager.BallPos.X) * 1024) - GameBallRect.Width / 2,
                (int)((0.02f + 0.96f * MenuMgr.GameManager.BallPos.Y) * 768) - GameBallRect.Height / 2,
                GameBallRect);
        }

        public void RenderPaddles()
        {
            RenderSprite(gameTexture,
                (int)(0.05f * 1024) - GameRedPaddleRect.Width / 2,
                (int)((0.06f + 0.88f * MenuMgr.GameManager.LeftPaddlePos) * 768) - GameRedPaddleRect.Height / 2,
                GameRedPaddleRect);
            RenderSprite(gameTexture,
                (int)(0.95f * 1024) - GameBluePaddleRect.Width / 2,
                (int)((0.06f + 0.88f * MenuMgr.GameManager.RightPaddlePos) * 768) - GameBluePaddleRect.Height / 2,
                GameBluePaddleRect);
        }

        public void ShowWinner()
        {
           if (MenuMgr.GameManager.LeftPlayerLives == 0)
              RenderSprite(menuTexture,
                  512 - GameBlueWonRect.Width / 2, 300, GameBlueWonRect);
           else
              RenderSprite(menuTexture,
                  512 - GameRedWonRect.Width / 2, 300, GameRedWonRect);
        }

    }
}
